########################################################################
#  Wiizard - A Wii games manager
#  Copyright (C) 2023  CYBERDEViL
#
#  This file is part of Wiizard.
#
#  Wiizard is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  Wiizard is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
########################################################################


from PyQt5.QtWidgets import (
  QDialog,
  QGridLayout,
  QProgressBar,
  QPushButton,
  QMessageBox,
  QLabel,
  QCheckBox
)
from PyQt5.QtCore import Qt

from wiizard import globals as Global
from wiizard.images import DlImagesThread
from wiizard.const import (
  IMG_FRONT_COVER,
  IMG_FRONT_3D_COVER,
  IMG_DISC,
  IMG_FULL
)
from wiizard.models.settings import GameImageSettings
from wiizard.widgets.line import HLine
from wiizard.translations import _


""" This dialog will start the thread for downloading images
"""
class DlImagesProgressDialog(QDialog):
  def __init__(self, dlList, requestHandler, scraper, parent=None):
    QDialog.__init__(self, parent, Qt.Dialog)

    self.setWindowTitle(_("Download progress"))
    self.setModal(False)

    layout = QGridLayout(self)

    self.progressBar  = QProgressBar(self)
    self.cancelButton = QPushButton(_("Cancel"), self)

    maxi = 0
    for idv6Str in dlList:
      maxi += len(dlList[idv6Str])
    self.progressBar.setMaximum(maxi)
    self.progressBar.setFormat("%v / %m")
    self.progressBar.setValue(0)

    layout.addWidget(self.progressBar, 0, 0)
    layout.addWidget(self.cancelButton, 1, 0)

    self.thread = DlImagesThread(dlList, requestHandler, scraper)

    self.thread.progress.connect(self.updateProgress)
    self.thread.completed.connect(self.onCompleted)
    self.cancelButton.clicked.connect(self.cancel)

  def run(self):
    Global.ActiveThreads.append(self.thread)
    self.thread.start()
    self.show()

  def cancel(self):
    self.progressBar.setFormat(_("Cancelling.."))
    self.progressBar.setValue(0)
    self.cancelButton.setEnabled(False)
    self.thread.cancel()

  def updateProgress(self, value):
    self.progressBar.setValue(value)

  def onCompleted(self):
    self.thread.wait()
    Global.ActiveThreads.remove(self.thread)
    failed = self.thread.failed
    if failed:
      print("FAILED!")
      failedStr = ""
      for fail in failed:
        failedStr += fail + "\n"
      QMessageBox(0, _("Failed downloads"), failedStr).exec()
    self.thread.quit()
    self.close()
    Global.SharedGameImages.remakePixmaps()
    print("Done")


class DlImagesDialog(QDialog):
  def __init__(self, requestHandler, scraper, parent=None):
    QDialog.__init__(self, parent, Qt.Dialog)

    self.__requestHandler = requestHandler
    self.__scraper        = scraper
    self.__missing        = {
      IMG_FRONT_COVER   : [],
      IMG_FRONT_3D_COVER: [],
      IMG_FULL          : [],
      IMG_DISC          : []
    }

    for sourceName, source in Global.Sources.localDirectories.items():
      missing = source.findMissingImages()
      self.__missing[IMG_FRONT_COVER]    += missing[IMG_FRONT_COVER]
      self.__missing[IMG_FRONT_3D_COVER] += missing[IMG_FRONT_3D_COVER]
      self.__missing[IMG_FULL]           += missing[IMG_FULL]
      self.__missing[IMG_DISC]           += missing[IMG_DISC]

    for sourceName, source in Global.Sources.devicePartitions.items():
      missing = source.findMissingImages()
      self.__missing[IMG_FRONT_COVER]    += missing[IMG_FRONT_COVER]
      self.__missing[IMG_FRONT_3D_COVER] += missing[IMG_FRONT_3D_COVER]
      self.__missing[IMG_FULL]           += missing[IMG_FULL]
      self.__missing[IMG_DISC]           += missing[IMG_DISC]

    for sourceName, source in Global.Sources.filePartitions.items():
      missing = source.findMissingImages()
      self.__missing[IMG_FRONT_COVER]    += missing[IMG_FRONT_COVER]
      self.__missing[IMG_FRONT_3D_COVER] += missing[IMG_FRONT_3D_COVER]
      self.__missing[IMG_FULL]           += missing[IMG_FULL]
      self.__missing[IMG_DISC]           += missing[IMG_DISC]

    frontMissingCount   = 0
    front3dMissingCount = 0
    missingFront   = 0
    missingFront3d = 0
    missingFull    = 0
    missingDisc    = 0
    missingCount   = 0

    if IMG_FRONT_COVER in self.__missing:
      missingFront += len(self.__missing[IMG_FRONT_COVER])

    if IMG_FRONT_3D_COVER in self.__missing:
      missingFront3d += len(self.__missing[IMG_FRONT_3D_COVER])

    if IMG_FULL in self.__missing:
      missingFull += len(self.__missing[IMG_FULL])

    if IMG_DISC in self.__missing:
      missingDisc += len(self.__missing[IMG_DISC])

    missingCount += missingFront
    missingCount += missingFront3d
    missingCount += missingFull
    missingCount += missingDisc

    self.setWindowTitle(_("Download images"))
    self.setModal(False)

    layout = QGridLayout(self)

    layout.addWidget(QLabel(_("<b>Download missing {} images</b>")
                     .format(missingCount), self), 0, 0, 1, 3, Qt.AlignCenter)

    layout.addWidget(HLine(self)                         , 1, 0, 1, 3)

    layout.addWidget(QLabel(_("<b>Type</b>"), self)      , 2, 0)
    layout.addWidget(QLabel(_("<b>Missing</b>"), self)   , 2, 1)
    layout.addWidget(QLabel(_("<b>Download</b>"), self)  , 2, 2)

    self.dlFrontCb = QCheckBox(self)
    layout.addWidget(QLabel(_("Front 2D"), self)         , 3, 0)
    layout.addWidget(QLabel(str(missingFront), self)     , 3, 1)
    layout.addWidget(self.dlFrontCb                      , 3, 2, Qt.AlignRight)

    self.dlFront3dCb = QCheckBox(self)
    layout.addWidget(QLabel(_("Front 3D"), self)         , 4, 0)
    layout.addWidget(QLabel(str(missingFront3d), self)   , 4, 1)
    layout.addWidget(self.dlFront3dCb                    , 4, 2, Qt.AlignRight)

    self.dlFullCb = QCheckBox(self)
    layout.addWidget(QLabel(_("Full"), self)             , 5, 0)
    layout.addWidget(QLabel(str(missingFull), self)      , 5, 1)
    layout.addWidget(self.dlFullCb                       , 5, 2, Qt.AlignRight)

    self.dlDiscCb = QCheckBox(self)
    layout.addWidget(QLabel(_("Disc"), self)             , 6, 0)
    layout.addWidget(QLabel(str(missingDisc), self)      , 6, 1)
    layout.addWidget(self.dlDiscCb                       , 6, 2, Qt.AlignRight)

    layout.addWidget(HLine(self)                         , 7, 0, 1, 3)

    langInfoLabel = QLabel(_(f"Preferred language is "
                           f"<b>{GameImageSettings.PreferredLang}</b>, "
                           f"fallback language is "
                           f"<b>{GameImageSettings.FallbackLang}</b> and "
                           f"any fallback is set to "
                           f"<b>{GameImageSettings.AnyFallback}</b>"), self)
    langInfoLabel.setToolTip(_("Preferred image language and fallback "
                               "language can be set from Settings."))
    langInfoLabel.setWordWrap(True)
    layout.addWidget(langInfoLabel                    , 8, 0, 1, 3)

    self.dlButton = QPushButton(_("Download"), self)
    if not missingCount:
      self.dlButton.setEnabled(False)
    layout.addWidget(self.dlButton                    , 9, 0, 1, 3, Qt.AlignCenter)

    self.dlButton.clicked.connect(self.__dlClicked)

  def __dlClicked(self):
    self.setEnabled(False)

    # Generate image type flags from checkboxes
    imgTypeFlags = 0
    if self.dlFrontCb.isChecked():
      imgTypeFlags |= IMG_FRONT_COVER
    if self.dlFront3dCb.isChecked():
      imgTypeFlags |= IMG_FRONT_3D_COVER
    if self.dlFullCb.isChecked():
      imgTypeFlags |= IMG_FULL
    if self.dlDiscCb.isChecked():
      imgTypeFlags |= IMG_DISC

    # create a download list with as primary key the id6 and as value the image
    # types to download
    dlList = {}
    for imgType in self.__missing:
      if not (imgType & imgTypeFlags):
        continue

      for idv6Str in self.__missing[imgType]:
        if idv6Str not in dlList:
          dlList.update({idv6Str: []})

        dlList[idv6Str].append(imgType)

    dlDialog = DlImagesProgressDialog(dlList, self.__requestHandler, self.__scraper, parent=self)
    dlDialog.finished.connect(self.__dlFinished)
    dlDialog.run()
    #self.close()

  def __dlFinished(self):
    self.close()
